-
Notifications
You must be signed in to change notification settings - Fork 85
Fix location assignment #482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
d00ba02 to
2e4b08e
Compare
2e4b08e to
aacd739
Compare
This comment was marked as outdated.
This comment was marked as outdated.
|
Note: I do use scalar-block-layouts if that matters - both enabled in Vulkan1.2, and I pass the command line argument for spirv-builder |
|
We don't care about scalar block layout or std430, we're just using whatever layout rustc gives us to ensure it's the same if you're using the same struct on shader and CPU side (at least since #380). If someone needs higher alignment (for silly wgpu uniform buffers or so), they should just I'm not actually too sure how scalar block layout and spirv-val interact precisely. Even though it's not enabled by default, we've never experienced any issues wrt layout with it being disabled. Even though Note that you are technically required to |
|
Even more minified code: #[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct ManyFloats {
a: f32,
b: f32,
c: f32,
}
#[spirv(vertex)]
pub fn main(out1: &mut ManyFloats, #[spirv(location = 3)] out2: &mut f32) {
const {
assert!(size_of::<ManyFloats>() == 12);
}
*out1 = Default::default();
*out2 = Default::default();
}This fails as well, as according to spec array elements can't share slots, each array element has to get their own slot. #[spirv(vertex)]
pub fn main(out1: &mut [f32; 3], out2: &mut f32) {
*out1 = Default::default();
*out2 = Default::default();
} |
|
I've reread the Vulkan spec on location assignment and noticed that locations are not assigned for every 16 bytes, but there's a totally custom algorithm on how locations are assigned. Implemented the layout algorithm in |
4123eda to
c2dfffe
Compare
|
Success! 🥳
Fun fact: I actually had it enabled only on the Vulkan12 feature side, and the spirv compiler threw an error and I had to enable it. |
|
I'll let @eddyb review this one as I am not qualified. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes location assignment for Input, Output, and UniformConstant storage classes to follow the Vulkan specification (16.1.4. Location and Component Assignment). Previously, locations were assigned one per declaration; now they're assigned based on type size where each scalar/vector occupies one location, structs sum their field locations, matrices multiply element locations by column count, and arrays multiply element locations by array size.
Key changes:
- Adds explicit
#[spirv(location = N)]attribute support with auto-incrementing behavior - Implements proper location size calculation based on type structure
- Validates location attributes cannot be combined with descriptor_set/binding
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
crates/rustc_codegen_spirv/src/symbols.rs |
Adds location symbol for the new attribute |
crates/rustc_codegen_spirv/src/attr.rs |
Implements Location attribute parsing and validation logic |
crates/rustc_codegen_spirv/src/spirv_type.rs |
Adds location_size() method to calculate locations per type; refactors sizeof() array logic for consistency |
crates/rustc_codegen_spirv/src/codegen_cx/entry.rs |
Implements location assignment logic with auto-increment and explicit location support; adds validation for attribute conflicts |
tests/compiletests/ui/spirv-attr/location_assignment*.rs |
New tests validating location assignment for various types (structs, arrays, matrices) with automatic and explicit locations |
tests/compiletests/ui/spirv-attr/location_assignment_explicit_overlap.* |
Test demonstrating overlap detection is delegated to spirv-val |
tests/compiletests/ui/spirv-attr/uniform-constant-storage-class.* |
Test for UniformConstant storage class with descriptor_set/binding |
tests/compiletests/ui/spirv-attr/bad-deduce-storage-class.* |
Updated to add descriptor_set/binding to Image parameters |
tests/compiletests/ui/spirv-attr/bool-inputs-err.stderr |
Updated error output to include new unsupported type error for bools |
tests/compiletests/ui/lang/core/ptr/allocate_const_scalar.stderr |
Updated error message for unsupported type in I/O declarations |
…s due to overlapping locations
c2dfffe to
0b9dc00
Compare
Locations for Input, Output (and UniformConstant, where I have no idea how they work without explicit descriptor_set and binding) were assigned one per declaration, whereas they should have been assigned
one per 16 bytesfollowing the Vulkan spec on 16.1.4. Location and Component Assignment.close #481.
Also adds an explicit location assignment, that keeps on counting from the last assigned value, just like glsl does:
rust-gpu/tests/compiletests/ui/spirv-attr/location_assignment_explicit.rs
Lines 25 to 32 in d00ba02
We don't check for overlaps when locations are manually assigned, leaving that for spirv-val:
rust-gpu/tests/compiletests/ui/spirv-attr/location_assignment_explicit_overlap.stderr
Lines 44 to 48 in d00ba02
See vulkan spec on 16.1.4. Location and Component Assignment and on 16.9.4. Offset and Stride Assignment of structs. spirv spec is irrelevant here, it simply declares the Location decoration exists, and leaves all further spec for the client APIs to handle.